#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# @Author : damone (summur0shine@gmail.com)
# @Link   : https://gitee.com/youngbull/autojump.git
# @Date   : 2018-1-14 04:47:46
# @Modify : yjw

import os
import subprocess
import sys
import cv2
import numpy as np
from matplotlib import pyplot as plt
import math
import time
import random


class DevTools:
    @staticmethod
    def press_screen(x, y, s_time):
        os.system("adb shell input swipe %d %d %d %d %d" % (x, y, x, y, s_time))

    @staticmethod
    def click(x, y):
        os.system("adb shell input tap " + str(x) + " " + str(y))

    @staticmethod
    def snap_screen(filename):
        os.system("adb shell /system/bin/screencap -p " + filename)

    @staticmethod
    def download_file(device_filename, host_filename):
        os.system("adb pull " + device_filename + " " + host_filename)

    @staticmethod
    def upload_file(host_filename, device_filename):
        os.system("adb push " + host_filename + " " + device_filename)

    @staticmethod
    def mk_dir(path):
        os.system("adb shell mkdir  " + path)


class Detecter:
    tmpl_filename = None
    template = None
    width = 0
    height = 0

    def __init__(self, tmpl_filename):
        os.environ["PATH"] = os.environ["PATH"] + ';' + os.getcwd() + os.path.sep + 'ADB'

        self.tmpl_filename = tmpl_filename
        self.template = cv2.imread(tmpl_filename, 0)
        self.width, self.height = self.template.shape[::-1]

    def detect_person(self, gray):
        method = eval('cv2.TM_CCOEFF')
        res = cv2.matchTemplate(gray, self.template, method)

        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
        top_left = max_loc
        bottom_right = (top_left[0] + self.width, top_left[1] + self.height)

        return top_left, bottom_right

    def detect_next_pos(self, image, top, bottom):
        image2 = image.copy()
        image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2HSV)
        h, s, v = cv2.split(image2)
        canny = cv2.Canny(h, 5, 5)
        canny |= cv2.Canny(s, 5, 5)
        canny |= cv2.Canny(v, 5, 5)
        thresh = cv2.threshold(canny, 0, 255, cv2.THRESH_BINARY)[1]
        thresh[top[1]:bottom[1], top[0]:bottom[0]] = 0
        _, cnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        # find contour
        dest_cnt = None
        dest_pos = None
        dest_y = 10000
        for c in cnts:
            # if the contour is too small, ignore it
            (x, y, w, h) = cv2.boundingRect(c)
            if y < 350 or w < 60 or h < 20:
                continue

            pos_t, _ = self.get_top_pos(c, y)
            if top[0] <= pos_t[0] <= bottom[0] and top[1] <= pos_t[1] <= bottom[1]:
                continue

            if y < dest_y:
                dest_y = y
                dest_cnt = c
                dest_pos = pos_t

        return dest_cnt, dest_pos

    def get_person_pos(self, top, bottom):
        x = int((top[0] + bottom[0]) / 2)
        y = bottom[1] - 15
        return x, y

    def get_top_pos(self, cnt, min_y):
        pos = [0, 0]
        count = 0
        for p in cnt:
            p = p[0]
            if p[1] - min_y < 5:
                count += 1
                pos[0] += p[0]
                pos[1] += p[1]
        pos[0] /= count
        pos[1] /= count
        return (int(pos[0]), int(pos[1])), count

    def get_center_pos(self, pos_s, pos_t):
        x = pos_t[0]
        y = pos_s[1]
        y = int(y - 0.60 * abs(x - pos_s[0]))
        if y < (pos_t[1] + 25) or y > (pos_t[1] + 150):
            y = pos_t[1] + 25
        return x, y

    def show_results(self, image, cnt, top, bottom, pos_s, pos_e, pos_t, count):
        cv2.circle(image, pos_t, 7, (255, 0, 0), -1)
        cv2.circle(image, pos_s, 7, (0, 0, 255), -1)
        cv2.circle(image, pos_e, 7, (0, 255, 0), -1)

        cv2.drawContours(image, [cnt], -1, (0, 255, 0), 2)
        cv2.rectangle(image, top, bottom, (0, 0, 255), 2)
        filename = "data/%d.png" % count
        cv2.imwrite(filename, image)

        # image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        # plt.imshow(image)
        # plt.show()

    def detect_image(self, filename, count):
        image = cv2.imread(filename)

        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        top, bottom = self.detect_person(gray)

        cnt, pos_t = self.detect_next_pos(image, top, bottom)
        pos_s = self.get_person_pos(top, bottom)
        pos_e = self.get_center_pos(pos_s, pos_t)
        self.show_results(image, cnt, top, bottom, pos_s, pos_e, pos_t, count)
        return pos_s, pos_e


def jump():
    count = 0
    det = Detecter("obj.png")
    x_random = random.uniform(35, 70)
    y_random = random.uniform(150, 300)
    game_sound_fn = "game_sound.png"
    while True:
        count += 1
        DevTools.snap_screen("/sdcard/" + game_sound_fn)
        DevTools.download_file("/sdcard/" + game_sound_fn, game_sound_fn)
        pos_s, pos_e = det.detect_image(game_sound_fn, count)
        s = math.sqrt(math.pow(pos_s[0] - pos_e[0], 2) + math.pow(pos_s[1] - pos_e[1], 2))
        if s > 700:
            t_ratio = 1.415
        elif s > 650:
            t_ratio = 1.420
        elif s > 600:
            t_ratio = 1.445
        elif s > 550:
            t_ratio = 1.450
        elif s > 500:
            t_ratio = 1.455
        elif s > 450:
            t_ratio = 1.485
        elif s > 400:
            t_ratio = 1.525
        elif s > 350:
            t_ratio = 1.525
        elif s > 300:
            t_ratio = 1.565
        elif s > 250:
            t_ratio = 1.595
        elif s > 200:
            t_ratio = 1.655
        elif s > 100:
            t_ratio = 1.695
        else:
            t_ratio = 1.511

        t = int(s * t_ratio)
        if t < 100 * t_ratio:
            t = 100 * t_ratio
        print(count, ":", s, ":", t_ratio)

        p_x = 560 + int(random.uniform(-x_random, x_random))
        p_y = 1500 + int(random.uniform(-y_random, y_random))
        DevTools.press_screen(p_x, p_y, t)
        time.sleep(random.uniform(.8, 2.5))


if __name__ == "__main__":
    jump()
